/* file contenente la definizione delle funzioni della classe ixp_graph che si occupano di caricare le 
	informazioni da file e di creare i grafi */
#include "ixp_graph.h"


ixp_graph::ixp_graph()
{
    if (leggi_grafo()==-1)
    {
        cerr<<"Errore di lettura file "<<internet_txt<<"!"<<endl;
        exit(1);
    }
    
    if (leggi_AS_speciali(0)==-1)
    {
        cerr<<"Errore di lettura file "<<excluded_txt<<"!"<<endl;
        exit(1);
    }
    
    if (leggi_AS_speciali(1)==-1)
    {
        cerr<<"Errore di lettura file "<<private_txt<<"!"<<endl;
        exit(1);
    }
    
    if (leggi_IXP()==-1)
    {
        cerr<<"Errore di lettura file "<<ixp_txt<<"!"<<endl;
        exit(1);
    }
    if (leggi_route_server()==-1)
    {
        cerr<<"Errore di lettura file "<<route_txt<<"!"<<endl;
        exit(1);
    }
    if (load_ixp_info()==-1)
    {
        cerr<<"Errore di lettura file "<<ixp_info<<"!"<<endl;
        exit(1);
    }
}


void ixp_graph::crea_grafi ()
{
	if ( create_global_graph( global, global_graph, global_mapping ) == -1 ) {
		cerr<<"Errore nel creare il grafo di Internet"<<endl;
		exit(1);
	}
	crea_global_nrs();
	if ( create_global_graph( global_nrs, global_graph_nrs, global_mapping_nrs ) == -1 ) {
		cerr<<"Errore nel creare il grafo di Internet senza RS"<<endl;
		exit(1);
	}
	crea_global_nrs_clique();
	if ( create_global_graph( global_nrs_clique, global_graph_nrs_clique, 
												global_mapping_nrs_clique ) == -1 ) {
		cerr<<"Errore nel creare il grafo di Internet con clique fra i peer dei RS"<<endl;
		exit(1);
	}
	cout<<"Creati i grafi di Internet"<<endl;
    crea_nodi_indotti();
    cout<<"Creati nodi indotti (con e senza Route Server)."<<endl;
    crea_link_indotti();
    cout<<"Creati link indotti (con e senza Route Server)."<<endl;
    crea_sottografi (link_indotti, nodi_indotti, grafi);
    cout<<"Creati grafi"<<endl;
	crea_sottografi (link_indotti_nrs, nodi_indotti_nrs, grafi_nrs);
	cout<<"Creati grafi senza Route Server (puri)"<<endl;
    crea_grafi_clique(grafi_nrs_clique);
    cout<<"Creati grafi senza Route Server (con clique)"<<endl;
    
}


//by Alessandro Iaria
void ixp_graph::crea_grafi_clique(map<int,igraph_t>& tmp)
{
    igraph_vector_t v;
    crea_sottografi (link_indotti_nrs, nodi_indotti_nrs, tmp);
    //scorro i rs
    for (map<int, unsigned int>::iterator itr_rs=route_server.begin(); itr_rs!=route_server.end(); itr_rs++)
    {
        //variabile in cui salvare gli elementi per fare la clique
        set<unsigned int> AS;
        //scorro i link per l'id di quel rs
        for (set<pair<unsigned int, unsigned int> > ::iterator itr_link=link_indotti[(*itr_rs).first].begin(); 
                                                                        itr_link!=link_indotti[(*itr_rs).first].end(); itr_link++)
            //se il primo è rs
            if ((*itr_link).first == (*itr_rs).second)
                AS.insert((*itr_link).second);
            else if (((*itr_link).second == (*itr_rs).second))
                AS.insert((*itr_link).first);
        //numero di coppie n*(n-1)/2, da moltiplicare per 2 quindi n*(n-1)
        int n=AS.size()*(AS.size()-1);
        if (n!=0)
        {
            igraph_vector_init(&v, n);
            int ind=0;
            for (set<unsigned int>::iterator itr_as1=AS.begin(); itr_as1!=AS.end(); itr_as1++)
            {
                set<unsigned int>::iterator itr_tmp=itr_as1;
                itr_tmp++;
                for (set<unsigned int>::iterator itr_as2=itr_tmp; itr_as2!=AS.end(); itr_as2++)
                {
                    //creo la coppia con indice il mapping per l'AS sul grafo nrs
                    VECTOR(v)[ind++]=(int)nodi_indotti_nrs[(*itr_rs).first][(*itr_as1)];
                    VECTOR(v)[ind++]=(int)nodi_indotti_nrs[(*itr_rs).first][(*itr_as2)];
                }
            }
            if (int ret=igraph_add_edges(&(tmp[(*itr_rs).first]), &v, 0) != 0)
            {
                cout<<"Errore di aggiunta rami: "<<ret<<endl;
                exit(1);
            }
            igraph_vector_destroy(&v);
            igraph_simplify(&(tmp[(*itr_rs).first]), true, true );
        }
    }
}


//by Giacomo Tanganelli
int ixp_graph::leggi_grafo()
{
	fstream f(internet_txt, ios::in);
	string s;
	
    if(!f)
        return -1;
	
    while(f.good()) 
    {
        getline(f, s);
		//split per dividere gli edges
		if ( !s.empty() && s[0] != '#' ) {
			string s1, s2;
			splitstring( s, "\t", s1, s2 );
			if ( !s1.empty() && !s2.empty() ) {
				unsigned int asn1, asn2;
				if ( converti_as( s1, asn1 ) == -1 || converti_as( s2, asn2 ) == -1 )
				{
					cout<<"AS in formato non corretto: "<<s1<<"-"<<s2<<endl;
					continue;
				}
				pair < unsigned int, unsigned int > edge ( asn1, asn2 );
				pair < unsigned int, unsigned int > inverso ( asn2, asn1 );
				set < pair < unsigned int, unsigned int > >::iterator it;
				it=global.find(inverso);
				if(it==global.end())
					global.insert(edge);
			}
		}
	}
    f.close();
    
    if ( DEBUG == 1 )
    	stampa_set_di_pair_uint_uint( "Link di Internet:", global );
    
	return 0;
}


//by Alessandro Iaria
int ixp_graph::leggi_IXP ()
{
	fstream f (ixp_txt, ios::in);
	string riga, tok1, tok2;
	unsigned int ind, AS;
	if(!f)
		return -1;
	
	while (f.good())
	{
		getline (f, riga);

		if ((riga.c_str())[0]!='#')
		{
            splitstring(riga, " ", tok1, tok2);
			if (!tok1.empty())
			{
				ind= atoi (tok1.c_str());
                if (ind!=0)
                {
				    if (!tok2.empty())
                    {
			            if (converti_as(tok2, AS) != -1)
                        {
                            bool ok=true;
                            for (set<pair<unsigned int, unsigned int> >::iterator itr=AS_esclusi.begin(); itr!=AS_esclusi.end(); itr++)
                                if ((*itr).first <=AS && (*itr).second >=AS)
                                    ok=false;
                            if (ok)
			                    membri_ixp[ind].insert(AS);
                            else if(DEBUG)
                                cout<<"Trovato AS da escludere: "<<AS<<" in IXP: "<<tok1<<endl;
                        }
                        else if(DEBUG)
                            cout<<"AS in formato non corretto: "<<tok2<<"!"<<endl;
                    }
                else if (DEBUG)
                    cout << "Trovato IXP_ID non valido: "<< tok1<<endl;
                }
            }
		}
	}

    f.close();
    if (DEBUG)
        debug_membri_ixp();
	return 0;
}


//by Alessandro Iaria
int ixp_graph:: load_ixp_info ()
{
    fstream f (ixp_info, ios::in);
	string riga, tok1, tok2;
	if(!f)
		return -1;
    while (f.good())
	{
		getline (f, riga);

		if ((riga.c_str())[0]!='#')
		{
            //IXP_ID
            splitstring(riga, ":", tok1, tok2);
            if(!tok1.empty())
            {
                int id=atoi(tok1.c_str());
                //controllo sia un numero
                if (id!=0)
                {
                    info_ixp nuovo;

                    //Nation
                    riga=tok2;
                    splitstring(riga, ":", tok1, tok2);
                    nuovo.nation=tok1;
                    //Continent
                    riga=tok2;
                    splitstring(riga, ":", tok1, tok2);
                    nuovo.continent=tok1;
                    //Short Name
                    riga=tok2;
                    splitstring(riga, ":", tok1, tok2);
                    nuovo.short_name=tok1;
                    //Long Name
                    riga=tok2;
                    splitstring(riga, ":", tok1, tok2);
                    nuovo.long_name=tok1;
                    //City, ultimo elemento della riga
                    nuovo.city=tok2;

                    ixps[id]=nuovo;

                    //Stampa id e contenuto
                    if (DEBUG)
                    {
                        cout<<"ID: "<<id<<" nat: "<<ixps[id].nation<<" cont: "<<ixps[id].continent<<" sn: "<<ixps[id].short_name<<endl;
                        cout<<" ln: "<<ixps[id].long_name<<" city: "<<ixps[id].city<<endl;
                    }
                }
            }
        }
    }
    return 0;
}


// by Alessio Casella
int ixp_graph:: leggi_AS_speciali ( int i )
{
	const char* path = ( i == 0 ) ? excluded_txt : private_txt;
	fstream f (path, ios::in);
	if ( !f )
		return -1;
		
	while ( !f.eof() ) {
		string s;
		getline( f, s );
		if ( !s.empty() && s[0] != '#' ) {
			string s1, s2;
			splitstring( s, "-", s1, s2 );
			if ( !s1.empty() && !s2.empty() ) {
				unsigned int asn1, asn2;
				if ( converti_as( s1, asn1 ) == -1 || converti_as( s2, asn2 ) == -1 )
					continue;
				if ( asn2 < asn1 ) {
					/* scambio gli asn se scritti in ordine inverso, poiche' devono rappresentare 
						un range con il primo numero che e' il limite inferiore del range */
					unsigned int app = asn1;
					asn1 = asn2;
					asn2 = app;
				}
				pair < unsigned int, unsigned int > range ( asn1, asn2 );
				if ( i == 0 )
					AS_esclusi.insert( range );
				else
					AS_privati.insert( range );
			}
		}
	}
	
	f.close();
	if ( DEBUG == 1 )
		stampa_AS_speciali(i);
	return 0;
}


// by Alessio Casella
int ixp_graph:: converti_as ( string ASN, unsigned int& asn_num )
{	
	/* rimuovo eventuali spazi iniziali e finali */
	size_t first = ASN.find_first_not_of( " \t" );
	if ( first == string::npos )
		/* la stringa contiene solo spazi */
		return -1;
	size_t last = ASN.find_last_not_of( " \t" );
	ASN = ASN.substr( first, last-first+1 );
	
	/* separo i 16 bit piu' significativi da quelli meno significativi dell'asn */
	string s1, s2;
	splitstring( ASN, ".", s1, s2 );
	if ( s1.find_first_not_of( "0123456789" ) != string::npos 
		 || s2.find_first_not_of( "0123456789" ) != string::npos )
		/* le sottostringhe contengono caratteri che non sono cifre */
		return -1;
	
	/* ASN non e' in notazione asdot: s1 contiene l'intero asn */
	if ( s2.empty() ) {
		if ( is_32bit( s1 ) == -1 )
			/* s1 e' un numero non rappresentabile su 32 bit */
			return -1;
		asn_num = atof( s1.c_str() );
	}
	/* ASN e' in notazione asdot */
	else {
		if ( is_32bit( s1 ) == -1 || is_32bit( s1 ) == -1 )
			/* s1 o s2 sono numeri non rappresentabili su 32 bit */
			return -1;
		asn_num = atof( s2.c_str() );
		if ( asn_num > 65535 )
			/* s2 e' un numero non rappresentabile su 16 bit */
			return -1;
		unsigned int  msb = atof( s1.c_str() );
		if ( msb > 65535 )
			/* s1 e' un numero non rappresentabile su 16 bit */
			return -1;
		asn_num += msb * 65536;
	}
	return 0;
}


// by Alessio Casella
int ixp_graph:: is_32bit ( string str )
{
	/* verifico che str non contenga un numero rappresentabile su piu' di 32 bit, cioe' maggiore di 
		4294967295 (che e' un numero di 10 cifre);
		non posso convertire la stringa in unsigned e dopo fare la verifica	sull'unsigned ottenuto 
		dalla conversione perche' gli unsigned sono rappresentati su 32 bit */
		
	/* salto eventuali zeri iniziali */
	size_t non_zero = str.find_first_not_of( "0" );
	if ( non_zero != string::npos ) {
		str = str.substr( non_zero );
		size_t len = str.length();
		if ( len > 10 )
			return -1;
		if ( len == 10 ) {
			if ( str[0] > '4' )
				return -1;
			else if ( str[0] == '4' ) {
				string lsb = str.substr( 1 );
				if ( atol( lsb.c_str() ) > 294967295 )
					return -1;
			}
		}
	}
	return 0;
}


//by Giovanni Lelli
int ixp_graph::leggi_route_server(){  

	fstream f(route_txt, ios::in);
	string s;
	unsigned int ixp_id, rs;
	
    if(!f)
        return -1;
	
    while(f.good()) 
    {
        getline(f, s);
	if ( !s.empty() && s[0] != '#' ) {
			string s1, s2;
			splitstring( s, "\t", s1, s2 );
			if ( !s1.empty() && !s2.empty() ) {
				ixp_id = atoi( s1.c_str() );
				if ( ( ixp_id == 0 && s1.compare( "0" ) != 0 ) || converti_as( s2, rs ) == -1 )
				{
					cout<<"formato non corretto: "<<s1<<"-"<<s2<<endl;
					continue;
				}
				  route_server[ixp_id]=rs;
				  if ( membri_ixp.find( ixp_id ) != membri_ixp.end() )
				  /* inserisco il route server fra i membri, se conoscevo i membri dell'ixp */
					  membri_ixp[ixp_id].insert(rs);
			}
		}
	}
	if(DEBUG)
	debug_route_server();
    f.close();
	return 0;
}


//by Giovanni Lelli
void ixp_graph::crea_nodi_indotti()
{
	int nodo=0;
	int nodo_nrs=0;
    bool ok=true;
	bool check=true;
	map <int,unsigned int>::iterator ret;
	map <int, set <unsigned int> >::iterator it;   //iteratore della chiave di membri_ixp
	set <unsigned int>::iterator it_as;		//iteratore del set di membri_ixp
	set <pair <unsigned int, unsigned int> >::iterator priv;   //iteratore di AS_privati
	for (it=membri_ixp.begin(); it!=membri_ixp.end(); it++){
		ret=route_server.find((*it).first);
        unsigned int rs;
		if(ret==route_server.end()) 
			check=false;
		else	
			rs= route_server[(*it).first];		
		
		for (it_as=((*it).second).begin(); it_as!=((*it).second).end(); it_as++){
            ok=true;
			for(priv=AS_privati.begin(); priv!=AS_privati.end();priv++){
				if( (*it_as)>=(*priv).first && (*it_as)<=(*priv).second )
                {
                    ok=false;   
					break;
				}
            }
            if(ok){
					nodi_indotti[(*it).first].insert(pair<unsigned int,unsigned int>((*it_as),nodo));
                    nodo++;
					if(check){
						if((*it_as)!=rs){   //costruisco anche nodi_indotti_NRS
							nodi_indotti_nrs[(*it).first].insert(pair<unsigned int,unsigned int>((*it_as),nodo_nrs));
							nodo_nrs++;
						}
					}				
		    }
		}
	
        check=true;
		nodo_nrs=0;		
		nodo=0;	
		
	}
    if (DEBUG)
	    stampa_nodi_indotti();
}


//by Giacomo Tanganelli
void ixp_graph:: crea_link_indotti()
{
	set<pair <unsigned int,unsigned int> >::iterator it;
	for ( it=global.begin() ; it != global.end(); it++ ){
		unsigned int primo=(*it).first;
		unsigned int secondo=(*it).second;
		map<int, map <unsigned int, unsigned int> >::iterator it_ixp;

		for ( it_ixp=nodi_indotti.begin() ; it_ixp != nodi_indotti.end(); it_ixp++ )
   		{
			if( (((*it_ixp).second).find(primo)!=((*it_ixp).second).end()) && (((*it_ixp).second).find(secondo)!=((*it_ixp).second).end()) )
			{
				pair < unsigned int, unsigned int > edge ( primo, secondo );				
				link_indotti[(*it_ixp).first].insert(edge);
			}		
		}

		for ( it_ixp=nodi_indotti_nrs.begin() ; it_ixp != nodi_indotti_nrs.end(); it_ixp++ )
   		{
			if( (((*it_ixp).second).find(primo)!=((*it_ixp).second).end()) && (((*it_ixp).second).find(secondo)!=((*it_ixp).second).end()) )
			{
				pair < unsigned int, unsigned int > edge ( primo, secondo );				
				link_indotti_nrs[(*it_ixp).first].insert(edge);
			}		
		}
	}
	if ( DEBUG == 1 )
		stampa_link_indotti();
}


//by Giovanni Lelli
void ixp_graph::crea_sottografi( map <int, set <pair <unsigned int,unsigned int> > > & link,
map <int, map <unsigned int, unsigned int> > & nodi, map<int,igraph_t>& graph )
{
    map <int, map <unsigned int,unsigned int> >::iterator it_ixp;
    set <pair <unsigned int,unsigned int> >::iterator it_ASN;
  
    map <unsigned int, unsigned int>::iterator m;
    unsigned int map1;
    unsigned int map2;
    igraph_vector_t vettore;
    igraph_t subgraph;
    
   for(it_ixp=nodi.begin(); it_ixp!=nodi.end(); it_ixp++){
        int dim=0;
        if ( link.find( it_ixp->first ) != link.end() )
        	dim = link[it_ixp->first].size();
        igraph_vector_init(&vettore,dim*2);
        int i=0;
        int vertex=it_ixp->second.size();
        if ( link.find( it_ixp->first ) != link.end() )
        	for(it_ASN=link[it_ixp->first].begin(); it_ASN!=link[it_ixp->first].end(); it_ASN++){
            	//mapping prendendo da link il primo ASN relativo all'IXP in questione ed usandolo
            	//come chiave all'interno della struttura nodi
            	map1=nodi[(*it_ixp).first][(*it_ASN).first];
            	VECTOR(vettore)[i]=map1;
            	i++;
            	//mapping prendendo da link il secondo ASN relativo all'IXP in questione ed usandolo
            	//come chiave all'interno della struttura nodi
            	map2=nodi[(*it_ixp).first][(*it_ASN).second];
            	VECTOR(vettore)[i]=map2;
            	i++;
        	}
        
        
        int ret=igraph_create(&subgraph, &vettore, vertex, false);
        if (ret==IGRAPH_EINVEVECTOR || ret==IGRAPH_EINVVID){
            cout<<"Errore nel creare i grafi: "<<ret<<endl;
            exit(1);
        }
        graph[(*it_ixp).first]=subgraph;
        if (DEBUG==1)
   	    {
   		    unsigned int len = igraph_vector_size( &vettore );
   		    cout<<"IXP ID:"<<(*it_ixp).first<<endl;
		    for ( unsigned int i = 0; i < len-1; i+=2 ) {
			    cout<<"\t"<<VECTOR(vettore)[i]<<" - "<<VECTOR(vettore)[i+1]<<endl;
		    }
        }
        igraph_vector_destroy(&vettore);
   }
}


//by Giacomo Tanganelli
int ixp_graph::create_global_graph ( const set < pair < unsigned int, unsigned int > >& link, 
										igraph_t& graph, map < unsigned int, unsigned int >& mapping )
{
	set <pair <unsigned int,unsigned int> >::const_iterator it;
	unsigned int asn1;
	unsigned int asn2;
	int i=0;
	int v=0;
	pair<map<unsigned int, unsigned int>::iterator,bool> ret;
	
	igraph_vector_t vettore;
    	
	
	int dim=link.size();
        igraph_vector_init(&vettore,dim*2);
	
	for ( it = link.begin(); it != link.end(); it++ ) {
	
		asn1 = (*it).first;
		asn2 = (*it).second;
		//mapping
		ret=mapping.insert( pair<unsigned int,unsigned int>(asn1,i) );
		if (ret.second==true)
 			i++;
		ret=mapping.insert( pair<unsigned int,unsigned int>(asn2,i) );
		if (ret.second==true)
 			i++;
 		//aggiungo edge
 		VECTOR(vettore)[v]=mapping[asn1];
 		v++;
 		VECTOR(vettore)[v]=mapping[asn2];
 		v++;
 		
	}
	int vertex=mapping.size();
	int r=igraph_create(&graph, &vettore, vertex, false);
        if (r==IGRAPH_EINVEVECTOR || r==IGRAPH_EINVVID){
            return -1;
        }
	return 0;
}


//by Alessio Casella
void ixp_graph:: crea_global_nrs ()
{
	/* scorro tutti i link di Internet: */
	set < pair < unsigned int, unsigned int > >::const_iterator it;
	unsigned int asn1;
	unsigned int asn2;
	for ( it = global.begin(); it != global.end(); it++ ) {
	
		asn1 = it->first;
		asn2 = it->second;
		
		/* inserisco il link in global_nrs solo se tale link non e' una connessione fra un membro di 
			un IXP e il route server dello stesso IXP, o se tale link e' anche una connessione 
			fra 2 membri normali in uno stesso IXP: */
		if ( ( !are_rs_and_member( asn1, asn2 ) && !are_rs_and_member( asn2, asn1 ) ) ||
				are_member_and_member ( asn1, asn2 ) )
			global_nrs.insert( *it );
	
	}
	
	if ( DEBUG == 1 )
    	stampa_set_di_pair_uint_uint( "Link di Internet senza RS:", global_nrs );
}


//by Alessio Casella
bool ixp_graph:: are_rs_and_member ( unsigned int rs, unsigned int as )
{
	map < int, unsigned int >::const_iterator it;
	int ixp_id;
	unsigned int rs_asn;
	for ( it = route_server.begin(); it != route_server.end(); it++ ) {
	
		ixp_id = it->first;
		rs_asn = it->second;
		
		if ( rs == rs_asn )
		/* rs e' route server dell'IXP ixp_id */
			if ( membri_ixp[ixp_id].find( as ) != membri_ixp[ixp_id].end() )
			/* as e' membro dell'IXP ixp_id */
				return true;
	
	}
	
	/* se sono arrivato qui, significa che o rs non e' route server in nessun IXP, o e' rs di IXP di 
		cui as non e' membro */
	return false;
}


//by Alessio Casella
bool ixp_graph:: are_member_and_member ( unsigned int as1, unsigned int as2 )
{
	map < int, set < unsigned int > >::const_iterator it;
	int ixp_id;
	map < int, unsigned int >::const_iterator rs;
	for ( it = membri_ixp.begin(); it != membri_ixp.end(); it++ ) {
	
		ixp_id = it->first;
		
		rs = route_server.find( ixp_id );
		if ( rs == route_server.end() || ( as1 != rs->second && as2 != rs->second ) )
		/* ne' as1 ne' as2 sono il route server dell'IXP ixp_id */
			if ( membri_ixp[ixp_id].find( as1 ) != membri_ixp[ixp_id].end() && 
					membri_ixp[ixp_id].find( as2 ) != membri_ixp[ixp_id].end() )
			/* as1 e as2 sono membri dell'IXP ixp_id */
				return true;
	
	}
	
	/* se sono arrivato qui, significa che as1 e as2 non sono membri normali di uno stesso IXP */
	return false;
}


//by Alessio Casella
void ixp_graph:: crea_global_nrs_clique ( )
{
	/* (1) inizialmente creo una copia esatta del grafo di Internet senza i route server */
	global_nrs_clique = global_nrs;
	
	/* (2) scorro tutti gli IXP con route server: */
	map < int, unsigned int >::const_iterator it;
	int ixp_id;
	unsigned int rs_asn;
	/* id del nodo che rappresenta il rs nel grafo di Internet con route server (global_graph): */
	unsigned int rs_node_id;
	for ( it = route_server.begin(); it != route_server.end(); it++ ) {
	
		ixp_id = it->first;
		rs_asn = it->second;
		
		map < unsigned int, unsigned int >::const_iterator rs_it;
		rs_it = global_mapping.find( rs_asn );
		if ( rs_it == global_mapping.end() )
		/* ignoro i RS che non hanno alcuna connessione in Internet */
			continue;
			
		rs_node_id = rs_it->second;
		
		/* asn dei membri connessi al RS */
		set < unsigned int > rs_peer;
		
		/* (2.1) scorro tutti i membri dell'IXP salvando gli asn dei membri connessi al RS */
		set < unsigned int >::const_iterator as;
		unsigned int asn;
		/* id del nodo che rappresenta il membro nel grafo di Internet con RS (global_graph) */
		unsigned int as_node_id;
		for ( as = membri_ixp[ixp_id].begin(); as != membri_ixp[ixp_id].end(); as++ ) {
		
			asn = *as;
			
			if ( asn != rs_asn ) {
			/* il membro non e' il RS stesso */
				map < unsigned int, unsigned int >::const_iterator as_it;
				as_it = global_mapping.find( asn );
				if ( as_it == global_mapping.end() )
				/* ignoro i membri che non hanno alcuna connessione in Internet */
					continue;
					
				as_node_id = as_it->second;
				
				igraph_bool_t connesso_al_rs;
				igraph_are_connected( &global_graph, as_node_id, rs_node_id, &connesso_al_rs );
				if ( connesso_al_rs )
					rs_peer.insert( asn );
			}
		}
		
		/* (2.2) aggiungo a global_nrs_clique i link fra i peer del RS */
		set < unsigned int >::const_iterator as1;
		set < unsigned int >::const_iterator as2;
		unsigned int asn1, asn2;
		for ( as1 = rs_peer.begin(); as1 != rs_peer.end(); as1++ ) {
			asn1 = *as1;
			as2 = as1;
			as2++;
			for ( ; as2 != rs_peer.end(); as2++ ) {
				asn2 = *as2;
				pair < unsigned int, unsigned int > link ( asn1, asn2 );
				pair < unsigned int, unsigned int > link_inv ( asn2, asn1 );
				if ( global_nrs_clique.find( link ) == global_nrs_clique.end() &&
						global_nrs_clique.find( link_inv ) == global_nrs_clique.end() )
					/* aggiungo il link solo se non c'era gia' */
					global_nrs_clique.insert( link );
			}
		}
	
	}
	
	if ( DEBUG == 1 )
    	stampa_set_di_pair_uint_uint( "Link di Internet con clique fra i peer dei RS:", 
    																	global_nrs_clique );
}


